{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Introduction to atomman: Cluster generators\n",
    "\n",
    "*added version 1.4.0*\n",
    "\n",
    "In addition to crystal structures, atomman has tools supporting calculations involving small atomic clusters.  "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 1. BondAngleMap\n",
    "\n",
    "__NOTE__ The methods associated with this class are still in development and testing and therefore may undergo substantial updates within the next few versions. Examples also to come later...\n",
    "\n",
    "The BondAngleMap class generates three atom clusters to explore and map the bond angle energies associated with an interatomic potential.  This is meant to provide a means of characterizing a potential's three-body interactions. \n",
    "\n",
    "### 1.1. Method and theory\n",
    "\n",
    "The phase space associated with a cluster of three atoms i, j and k is characterized using the following three coordinates:\n",
    "\n",
    "- __$r_{ij}$__ being the radial distance between atoms i and j.\n",
    "- __$r_{ik}$__ being the radial distance between atoms i and k.\n",
    "- __$\\theta_{ijk}$__ being the angle between the ij and ik vectors.\n",
    "\n",
    "A map of the phase space can then be constructed by taking equal steps along these three coordinates according to sampling parameters rmin, rmax, and rnum for the two radial distances and thetamin, thetamax and thetanum for the angle.  For each configuration, the radial distance between atoms j and k can be computed using $r_{jk} = \\sqrt{r_{ij}^2 + r_{ik}^2 - 2 r_{ij} r_{ik} \\cos(\\theta_{ijk})}$ \n",
    "\n",
    "Atomic cluster configurations are constructed based on the three coordinates as\n",
    "- atom i is positioned at $[0.0, 0.0, 0.0]$\n",
    "- atom j is positioned at $[r_{ij}, 0.0, 0.0]$\n",
    "- atom k is positioned at $[r_{ik} \\cos(\\theta_{ijk}), r_{ik} \\sin(\\theta_{ijk}), 0.0] $\n",
    "- box dimensions of at least $\\pm$rmax in all directions and non-periodic boundary conditions.\n",
    "                "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 1.2. Initializing a BondAngleMap\n",
    "\n",
    "The cluster coordinates (r distances and theta angles) are required and can be specified in one of three ways.\n",
    "\n",
    "- A data model containing all the information.\n",
    "- Input ranges (rmin, rmax, rnum, thetamin, thetamax, thetanum).  The r\n",
    "  range parameters will be used to generate values for both r_ij and\n",
    "  r_ik.\n",
    "- Explicitly giving r_ij, r_ik and theta values.\n",
    "\n",
    "Parameters\n",
    "        \n",
    "- __model__ (*str, path-like object or DataModelDict, optional*) Collected data model results from a series of runs.  Contains both coordinate information and energy values.\n",
    "- __rmin__ (*float, optional*) The minimum value used for the r_ij and r_ik spacings.\n",
    "- __rmax__ (*float, optional*) The maximum value used for the r_ij and r_ik spacings.\n",
    "- __rnum__ (*float, optional*) The number of values used for the r_ij and r_ik spacings.\n",
    "- __thetamin__ (*float, optional*) The minimum value used for the theta angles.\n",
    "- __thetamax__ (*float, optional*) The maximum value used for the theta angles.\n",
    "- __thetanum__ (*float, optional*) The number of values used for the theta angles.\n",
    "- __r_ij__ (*array-like, optional*) All r_ij values used.  If given, the lengths of r_ij, r_ik and theta need to be the same.\n",
    "- __r_ik__ (*array-like, optional*) All r_ik values used.  If given, the lengths of r_ij, r_ik and theta need to be the same.\n",
    "- __theta__ (*array-like, optional*) All theta values used.  If given, the lengths of r_ij, r_ik and theta need to be the same.\n",
    "- __energy__ (*array-like, optional*) All measured energies.  If r_ij, r_ik and theta are given then all should be the same length.  If the coordinate range parameters are given, then the energies should be of length rnum*rnum*thetanum and ordered to correspond to three embedded loops with r_ij iterating in the outside loop, r_ik in the middle and theta in the inside.  If energy is not given, then all values will initially be set to np.nan.\n",
    "- __symbols__ (*str or list, optional*) Element model symbol(s) to associate with the three atoms if/when systems are created.  Can either be a single symbol to assign to all atoms, or three symbols to assign to atoms i, j, and k individually.  Not needed if systems are not generated by this class."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 1.3. Iterators \n",
    "\n",
    "#### 1.3.1. itercoords\n",
    "\n",
    "Iterates through the set of r_ij, r_ik, r_jk and theta_ijk coordinates for each configuration. \n",
    "\n",
    "#### 1.3.2. itersystems()\n",
    "\n",
    "Iterates through the three-body coordinates based on the r and theta values. \n",
    "\n",
    "Parameters\n",
    "        \n",
    "- __symbols__ (*str or list, optional*) The element model symbols to assign to the atoms.  Can either be one value for all atoms, or three values for each atom individually. If not given here, will use the values set during class initialization.\n",
    "- __copy__ (*bool, optional*) If False (default), then the yielded system is the same object with the coordinates shifted.  If True, each yielded system is a new object.\n",
    "\n",
    "Yields\n",
    "\n",
    "- (*atomman.System*) The atomic system containing the three-body cluster. "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 1.4. Data representations\n",
    "\n",
    "#### 1.4.1. df\n",
    "\n",
    "Generates a pandas.DataFrame of the coordinates and the associated energies, if measured.\n",
    "\n",
    "#### 1.4.2. model()\n",
    "\n",
    "Loads or generates a bond angle map data model.\n",
    "\n",
    "Note: Generating data models is currently limited to regular values, i.e. ones which the coordinates correspond to embedded loops with r_ij iterating in the outside loop, r_ik in the middle loop and theta in the inside loop.\n",
    "\n",
    "Parameters\n",
    "\n",
    "- __model__ (*str, file-like object or DataModelDict, optional*) The data model content or file containing the bond angle map data. If given, the content will be read in and set to the current object. If not given, then a data model will be returned for the object.\n",
    "- __length_unit__ (*str, optional*) The unit of length to save the rmin and max values in when generating a data model.  Default value is 'angstrom'.\n",
    "- __energy_unit__ (*str, optional*) The unit of energy to save the energy values in when generating a data model.  Default value is 'eV'.\n",
    "\n",
    "Returns\n",
    "\n",
    "- (*DataModelDict.DataModelDict*) The data model containing the bond angle map coordinate information and measured energies.  Only returned if model is not given as a parameter.\n",
    "\n",
    "Raises\n",
    "\n",
    "- *(ValueError*) If the data is irregular, i.e. coordinates do not conform to embedded loops with r_ij in the outer loop, r_ik in the middle loop and theta in the inside loop.\n",
    "\n",
    "#### 1.4.3. save_table()\n",
    "\n",
    "Saves a tabulated representation of the coordinates and energy values to a file.\n",
    "\n",
    "Parameters\n",
    "        \n",
    "- __filename__ (*str*) The path to the file where the table will be saved.\n",
    "- __include_header__ (*bool*) If True (default) then header comments will be listed at the top of the file."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 1.5 Data analysis methods\n",
    "\n",
    "#### 1.5.1. pdf()\n",
    "\n",
    "Returns the probability density function for the energy\n",
    "        \n",
    "Parameters\n",
    "\n",
    "- __nbins__ (*int, optional*) The number of histogram bins to use.  Default value is 301.\n",
    "- __energymin__ (*float, optional*) The minimum energy bound to consider.  Default value is -15.0.\n",
    "- __energymax__ (*float, optional*) The maximum energy bound to consider.  Default value is 15.0.\n",
    "\n",
    "Returns\n",
    "        \n",
    "- __pdf__ (*numpy.NDArray*) The probability density function associated with each bin.\n",
    "- __centers__ (*numpy.NDArray*) The center values for each bin.\n",
    "            \n",
    "#### 1.5.2. cumulative_pdf()\n",
    "\n",
    "Returns the cumulative probability density function for the energy.\n",
    "        \n",
    "Parameters\n",
    "        \n",
    "- __nbins__ (*int, optional*) The number of histogram bins to use.  Default value is 301.\n",
    "- __energymin__ (*float, optional*) The minimum energy bound to consider.  Default value is -15.0.\n",
    "- __energymax__ (*float, optional*) The maximum energy bound to consider.  Default value is 15.0.\n",
    "\n",
    "Returns\n",
    "        \n",
    "- __cum_pdf__ (*numpy.NDArray*) The cumulative probability density function associated with each bin.\n",
    "- __centers__ (*numpy.NDArray*) The center values for each bin.\n",
    "            \n",
    "#### 1.5.3. plot_pdf()\n",
    "\n",
    "Generates a plot of the probability density function of the energy.\n",
    "\n",
    "Parameters\n",
    "        \n",
    "- __nbins__ (*int, optional*) The number of histogram bins to use.  Default value is 301.\n",
    "- __energymin__ (*float, optional*) The minimum energy bound to consider.  Default value is -15.0.\n",
    "- __energymax__ (*float, optional*) The maximum energy bound to consider.  Default value is 15.0.\n",
    "- __matplotlib_axes__ (*matplotlib.Axes.axes, optional, optional*) An existing plotting axis to add the pdf plot to.  If not given, a new figure object will be generated.\n",
    "- __\\*\\*kwargs__ (*any, optional*) Any additional key word arguments will be passed to matplotlib.pyplot.figure for generating a new figure object (if axis is not given).\n",
    "        \n",
    "Returns\n",
    "        \n",
    "- (*matplotlib.Figure*) The generated figure.  Not returned if matplotlib_axes is given.\n",
    "            \n",
    "#### 1.5.4. plot_cumulative_pdf()\n",
    "\n",
    "Generates a plot of the cumulative probability density function of the energy.\n",
    "\n",
    "Parameters\n",
    "        \n",
    "- __nbins__ (*int, optional*) The number of histogram bins to use.  Default value is 301.\n",
    "- __energymin__ (*float, optional*) The minimum energy bound to consider.  Default value is -15.0.\n",
    "- __energymax__ (*float, optional*) The maximum energy bound to consider.  Default value is 15.0.\n",
    "- __matplotlib_axes__ (*matplotlib.Axes.axes, optional, optional*) An existing plotting axis to add the pdf plot to.  If not given, a new figure object will be generated.\n",
    "- __\\*\\*kwargs__ (*any, optional*) Any additional key word arguments will be passed to matplotlib.pyplot.figure for generating a new figure object (if axis is not given).\n",
    "        \n",
    "Returns\n",
    "        \n",
    "- (*matplotlib.Figure*) The generated figure.  Not returned if matplotlib_axes is given."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
